package com.freedom.web.mymvc;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import com.freedom.web.mymvc.handler.HttpUserHandler;
import com.freedom.web.mymvc.utils.LoggerUtils;
import com.freedom.web.mymvc.utils.ConstantsUtils;
import com.freedom.web.mymvc.utils.PropertiesUtils;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.stream.ChunkedWriteHandler;

public class Server {
	private static final Logger logger = LogManager.getLogger(Server.class);
	static {
		// 触发route程序加载
		try {
			Class.forName(ConstantsUtils.ROUTE_CLASS);
		} catch (ClassNotFoundException e) {
			LoggerUtils.error(logger, e.toString());
			System.exit(-1);
		}
	}

	public static void main(String[] args) {
		// 获取属性文件
		PropertiesUtils p = PropertiesUtils.getInstance();
		int port = p.getNettyPort();
		int bossNum = p.getNettyBoss();
		int workerNum = p.getNettyWorker();
		final int maxSize = p.getMaxSize();
		LoggerUtils.info(logger,
				"port: " + port + " bossNum: " + bossNum + " workerNum: " + workerNum + " maxSize: " + maxSize);
		// 创建http服务器
		EventLoopGroup bossGroup = new NioEventLoopGroup(bossNum);
		EventLoopGroup workerGroup = new NioEventLoopGroup(workerNum);
		try {
			ServerBootstrap b = new ServerBootstrap();
			b.option(ChannelOption.SO_BACKLOG, 4096);
			b.group(bossGroup, workerGroup)//
					.channel(NioServerSocketChannel.class)//
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel ch) throws Exception {
							// 这几个都是框架需要，完成HTTP协议的编解码所用
							LoggerUtils.debug(logger, "one connection " + ch);
							ch.pipeline().addLast("http-decoder", new HttpRequestDecoder());
							ch.pipeline().addLast("http-aggregator", new HttpObjectAggregator(maxSize));// 默认1M
							ch.pipeline().addLast("http-encoder", new HttpResponseEncoder());
							ch.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
							// 真正处理用户级业务逻辑的地方
							ch.pipeline().addLast("http-user-defined", new HttpUserHandler());
						}
					});
			// 开始真正绑定端口进行监听
			ChannelFuture future = b.bind("0.0.0.0", port).sync();
			LoggerUtils.info(logger, "listening on 0.0.0.0:" + port);
			future.channel().closeFuture().sync();
		} catch (Exception e) {
			LoggerUtils.error(logger, e.toString());
		} finally {
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
			LoggerUtils.info(logger, "server exit...");
		}
	}
}
